package vois

import (
	"strings"

	"code.google.com/awwwe-browser/data"
)

// data for <sayas-text></sayas-text>
type VOISSayasText struct {
	Text  string
	Sayas string
}

// data for <sayas-at></sayas-at>
type VOISSayasAt struct {
	Xpath string
	Sayas string
}

// the content on a web page may be of different types.
// there are also types for feeds.
// they are listed below.
type VOISContentType int

const (
	NoContentType VOISContentType = iota
	ArticleContentType
	NavigationContentType
	FormContentType
	AtomContentType
	RSSContentType
	GameContentType
)

// general catch all content information for the view.
type VOISContent struct {
	ContentType         VOISContentType
	IsMainContent       bool
	AllowLinkingOffSite bool
	Description         string
	Condition           string
	Title               string
	TitleAt             string
	OnlySpeakAt         string
	NeverSpeakAt        string
	// article only data
	OpenWithVideo bool
	// form only data
	FormAt string
}

// returns a speakable phrase for the type.
func (vc VOISContent) TypeToVoice() string {
	var t string
	t = data.EmptyString
	switch vc.ContentType {
	case ArticleContentType:
		t = "article"
	case NavigationContentType, AtomContentType, RSSContentType:
		t = "navigation"
	case FormContentType:
		t = "form"
	}
	return t
}

// returns a pointer to a new VOISContent.
func newVOISContent() *VOISContent {
	var v VOISContent
	v.ContentType = NoContentType
	return &v
}

// information contained in vois markup files.
type VOISData struct {
	SiteURL             string
	SiteName            string
	AllowLinkingOffSite bool
	SayasText           []VOISSayasText
	SayasAt             []VOISSayasAt
	Content             []*VOISContent
	AtomLinkAt          string
	RSSLinkAt           string
	GameLinkAt          string
}

// returns a pointer to a new VOISData.
func newVOISData() *VOISData {
	var v VOISData
	v.SayasText = make([]VOISSayasText, 0, 5)
	v.SayasAt = make([]VOISSayasAt, 0, 5)
	v.Content = make([]*VOISContent, 0, 5)
	v.AtomLinkAt = `/html/head/link[@rel="alternate" and @type="application/atom+xml"]`
	v.RSSLinkAt = `/html/head/link[@rel="alternate" and @type="application/rss+xml"]`
	v.GameLinkAt = `/html/head/link[@rel="awwwe:game"]`
	return &v
}

// <link rel="awwwe:game" title="dungeon game" href="http://localhost:9998/game" />

// returns true if there is any content which is main content.
func (this *VOISData) HasMainContent() bool {
	var c *VOISContent
	for _, c = range this.Content {
		if c.IsMainContent {
			return true
		}
	}
	return false
}

// translate using sayas text data.
func (this *VOISData) Translate(src string) string {
	var sayastext VOISSayasText
	var s string
	var i, length int
	if len(this.SayasText) > 0 {
		sayastext = this.SayasText[0]
		s = strings.Replace(src, sayastext.Text, sayastext.Sayas, -1)
		for i = 1; i < length; i++ {
			sayastext = this.SayasText[i]
			s = strings.Replace(s, sayastext.Text, sayastext.Sayas, -1)
		}
		return s
	} else {
		return src
	}
}

// the vois markup for all RSS feeds.
var RSSVOISMarkup []byte = []byte(`<?xml version="1.0" encoding="utf-8"?>
<vois>

    <link-off-site />

    <rss-navigation>
        <condition>count(/rss/channel/item/link) &gt; 0</condition>
        <title>The list of new articles.</title>
        <items-at>
            /rss/channel/item
        </items-at>
    </rss-navigation>

</vois>`)

// the vois markup for all ATOM feeds.
var ATOMVOISMarkup []byte = []byte(`<?xml version="1.0" encoding="utf-8"?>
<vois>
  
    <link-off-site />

    <atom-navigation>
        <condition>count(/feed/entry[link[@rel="alternate"]]) &gt; 0</condition>
        <title>The list of new articles.</title>
        <entries-at>
            /feed/entry
        </entries-at>
    </atom-navigation>

</vois>`)

// the vois markup for all Game content in a web page.
var GameVOISMarkup []byte = []byte(`<?xml version="1.0" encoding="utf-8"?>
<vois>
  
    <game>
        <condition>count(/html/body/form[@role="awwwe:game"]) = 1</condition>
        <form-at>/html/body/form[@role="awwwe:game"]</form-at>
    </game>

</vois>`)

type VOISError struct {
	message string
}

// builds a vois error
func buildVOISError(mess string) VOISError {
	var err VOISError
	err.message = mess
	return err
}

// returns the message in an error.
func (err VOISError) Error() string {
	return err.message
}
